package com.ruoyi.core.service.impl;

import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.common.enums.ClientType;
import com.ruoyi.common.enums.ProductType;
import com.ruoyi.common.exception.CustomException;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.RedisCacheKeyHelper;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.spring.SpringUtils;
import com.ruoyi.core.domain.CkConfig;
import com.ruoyi.core.domain.ClientProduct;
import com.ruoyi.core.domain.ClientProductUser;
import com.ruoyi.core.domain.ResourceStatus;
import com.ruoyi.core.domain.custombean.ClientProductCookieQueryResult;
import com.ruoyi.core.manager.ProductUserCookieResourceManager;
import com.ruoyi.core.mapper.CkConfigMapper;
import com.ruoyi.core.mapper.ClientProductMapper;
import com.ruoyi.core.mapper.ClientProductUserMapper;
import com.ruoyi.core.productuser.ClientProductUserPollStrategy;
import com.ruoyi.core.service.ClientOperationService;
import com.ruoyi.core.service.IClientProductUserService;
import com.ruoyi.core.vo.ClientProductUserCreateOperationVO;
import com.ruoyi.core.vo.ClientProductUserUpdateOperationVO;
import com.ruoyi.framework.utils.SessionHelper;
import com.ruoyi.framework.utils.UserLocalThreadHelper;
import io.jsonwebtoken.lang.Assert;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.*;

/**
 * client-product-userService业务层处理
 *
 * @author ruoyi
 * @date 2020-09-28
 */
@Service
public class ClientProductUserServiceImpl implements IClientProductUserService {
    @Autowired
    private ClientProductUserMapper clientProductUserMapper;

    @Autowired
    private RedisCache redisCache;

    @Autowired
    private ClientProductMapper clientProductMapper;

    @Autowired
    private CkConfigMapper ckConfigMapper;

    @Autowired
    private ClientOperationService clientOperationService;

    /**
     * 查询client-product-user
     *
     * @param id client-product-userID
     * @return client-product-user
     */
    @Override
    public ClientProductUser selectClientProductUserById(Long id) {
        return clientProductUserMapper.selectClientProductUserById(id);
    }

    /**
     * 查询client-product-user列表
     *
     * @param clientProductUser client-product-user
     * @return client-product-user
     */
    @Override
    public List<ClientProductUser> selectClientProductUserList(ClientProductUser clientProductUser) {
        List<ClientProductUser> clientProductUsers = clientProductUserMapper.selectClientProductUserList(clientProductUser);
        if (clientProductUsers == null || clientProductUsers.isEmpty()) {
            return Collections.emptyList();
        }
        clientProductUsers.forEach(item -> {
            Collection<String> keys = redisCache.keys(RedisCacheKeyHelper.getProductUserOnlineUsagePrefixKey(item.getProductId(), item.getId()) + "*");
            item.setOnlineUser((long) keys.size());
        });

        return clientProductUsers;
    }

    /**
     * 新增client-product-user
     *
     * @param clientProductUserCreateVO client-product-user
     * @return 结果
     */
    @Override
    public int add(ClientProductUserCreateOperationVO clientProductUserCreateVO) {

        if (clientProductMapper.selectClientProductById(clientProductUserCreateVO.getProductId()) == null) {
            String message = String.format("客户端产品 id:[%s]不存在", clientProductUserCreateVO.getProductId());
            throw new CustomException(message);
        }

//        ClientProductUser productUser = clientProductUserMapper.findByUsername(clientProductUserCreateVO.getUsername());
//        if (productUser != null && clientProductUserCreateVO.getProductId().equals(productUser.getProductId())) {
//            String message = String.format("客户端内置用户 [%s]已存在", clientProductUserCreateVO.getUsername());
//            throw new CustomException(message);
//        }

        ClientProductUserPollStrategy.clearIndexCache();

        ClientProductUser clientProductUser = new ClientProductUser();
        BeanUtils.copyProperties(clientProductUserCreateVO, clientProductUser);
        clientProductUser.setCreateTime(DateUtils.getNowDate());
        clientProductUser.setStatus(ResourceStatus.ENABLE);
        clientProductUser.setBackUpCookie(clientProductUserCreateVO.getBackUpCookie());
        clientProductUser.setCode(clientProductUserCreateVO.getCode());
        return clientProductUserMapper.insertClientProductUser(clientProductUser);
    }

    /**
     * 修改client-product-user
     *
     * @param clientProductUserUpdateVO client-product-user
     * @return 结果
     */
    @Override
    public int update(ClientProductUserUpdateOperationVO clientProductUserUpdateVO) {

        ClientProductUser productUser = clientProductUserMapper.selectClientProductUserById(clientProductUserUpdateVO.getId());
        if (productUser == null) {
            String message = String.format("客户端内置用户 id:[%s],用户名 [%s] 不存在", clientProductUserUpdateVO.getId(), clientProductUserUpdateVO.getUsername());
            throw new CustomException(message);
        }

        ClientProductUser clientProductUser = new ClientProductUser();
        BeanUtils.copyProperties(clientProductUserUpdateVO, clientProductUser);
        clientProductUser.setUpdateTime(DateUtils.getNowDate());
        int update = clientProductUserMapper.update(clientProductUser);
        // 更新缓存cookie
        ProductUserCookieResourceManager bean = SpringUtils.getBean(ProductUserCookieResourceManager.class);
        if (StringUtils.hasText(clientProductUserUpdateVO.getCookie())) {
            bean.setCookie(productUser.getId(), clientProductUserUpdateVO.getCookie());
        } else {
            bean.clean(productUser.getId());
        }

        return update;
    }

    /**
     * 批量删除client-product-user
     *
     * @param ids 需要删除的client-product-userID
     * @return 结果
     */
    @Override
    public int deleteClientProductUserByIds(Long[] ids) {
        ClientProductUserPollStrategy.clearIndexCache();
        return clientProductUserMapper.deleteClientProductUserByIds(ids);
    }

    /**
     * 删除client-product-user信息
     *
     * @param id client-product-userID
     * @return 结果
     */
    @Override
    public int deleteClientProductUserById(Long id) {
        return clientProductUserMapper.deleteClientProductUserById(id);
    }

    @Override
    public List<ClientProductUser> findByProductId(Long productId) {
        List<ClientProductUser> results = clientProductUserMapper.findByProductId(productId);
        if (results == null || results.isEmpty()) {
            return Collections.emptyList();
        }
        results.forEach(item -> {
            Collection<String> keys = redisCache.keys(RedisCacheKeyHelper.getProductUserOnlineUsagePrefixKey(item.getProductId(), item.getId()) + "*");
            item.setOnlineUser((long) keys.size());
        });
        return results;
    }

    @Override
    public ClientProductUser getClientProductUserRandomStrategy(Long productId) {
        return getClientProductUserRandomStrategyByUserId(productId,SecurityUtils.getLoginUser().getUser().getUserId(),false);
    }

    @Override
    public ClientProductUser getClientProductUserRandomStrategyByUserId(Long productId, Long userId,boolean needCookie) {
        List<ClientProductUser> clientProductUsers = clientProductUserMapper.findByProductId(productId);
        if (clientProductUsers == null || clientProductUsers.isEmpty()) {
            return null;
        }

        //判断是否存在指定的cookie,如果存在,则使用指定的cookie,否则使用随机的
        String specifyCookie = getSpecifyCookie(productId,userId);

        ClientProductUserPollStrategy.setClientProductUsers(clientProductUsers);
        ClientProductUser clientProductUser = ClientProductUserPollStrategy.get(productId);

        ClientProduct clientProduct = clientProductMapper.selectClientProductById(clientProductUser.getProductId());
        if(clientProduct == null){
            return null;
        }

        if(!needCookie && !needCookie(clientProduct.getName())){
            clientProductUser.setCookie("{\"status\": true}");
        }

        if(specifyCookie != null){
            clientProductUser.setCookie(specifyCookie);
        }

        clientProductUser.setUrl(clientProduct.getUrl());
        return clientProductUser;
    }

    private String getSpecifyCookie(Long productId,Long userId) {

        Assert.notNull(userId,"请重新登陆");

        CkConfig ckConfig = ckConfigMapper.findByUserIdAndProductId(userId,productId);
        if(ckConfig == null){
            return null;
        }
        ClientProductUser clientProductUser = clientProductUserMapper.selectClientProductUserById(ckConfig.getCkId());
        if(clientProductUser == null){
            return null;
        }
        return clientProductUser.getCookie();
    }

    @Override
    public List<ClientProductCookieQueryResult> productList() {
        return clientProductUserMapper.findAllProductCookies(1);
    }

    @Override
    public ClientProductUser getClientProductUserRandomStrategyByJsPlugin() {
        ClientProductUser clientProductUser = clientOperationService.getJsPluginProductUser();
        clientProductUser.setUsername(null);
        clientProductUser.setPassword(null);
        return clientProductUser;
    }

    private boolean needCookie(String name){
        return name.equals(ProductType.helium10.getName())
                || name.equals(ProductType.helium10Plugin.getName())
                || name.equals(ProductType.merchantwordsv2.getName())
                || name.equals(ProductType.junglescoutv2.getName())
                || (SessionHelper.isPluginRequest());
    }
}
